﻿using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;

namespace AutoBuildEntity
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class CreateEntityCommand
    {
        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 0x0100;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("9c4b1480-36bf-4f93-8720-c87a87369009");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly AsyncPackage package;
        private static DTE _dte;
        public string ProjectPath
        {
            get
            {
                ThreadHelper.ThrowIfNotOnUIThread();
                var item = _dte.SelectedItems.Item(1).ProjectItem;
                var projectPath = item.ContainingProject.FullName;
                return projectPath.Substring(0, projectPath.LastIndexOf('\\'));
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CreateEntityCommand"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        /// <param name="commandService">Command service to add command to, not null.</param>
        private CreateEntityCommand(AsyncPackage package, OleMenuCommandService commandService)
        {
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(this.Execute, menuCommandID);
            commandService.AddCommand(menuItem);
        }

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static CreateEntityCommand Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static async Task InitializeAsync(AsyncPackage package)
        {
            // Switch to the main thread - the call to AddCommand in CreateEntityCommand's constructor requires
            // the UI thread.
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
            Instance = new CreateEntityCommand(package, commandService);
            _dte = await package.GetServiceAsync(typeof(DTE)) as DTE;
        }

        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private void Execute(object sender, EventArgs e)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var item = _dte.SelectedItems.Item(1).ProjectItem;
            var filePath = item.FileNames[0];

            if (string.IsNullOrWhiteSpace(filePath))
            {
                ShowMessage("获取项目信息失败");
                return;
            }
            var fileNamespace = GetNamespace();
            var win = new UserWindow(fileNamespace, ProjectPath, filePath);
            if (win.IsEnabled)
                win.ShowDialog();
        }
        private string GetProjectPath()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var item = _dte.SelectedItems.Item(1).ProjectItem;
            return item.FileNames[0];
        }

        private string GetNamespace()
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var item = _dte.SelectedItems.Item(1).ProjectItem;
            var filename = item.FileNames[0];
            var projectName = item.ContainingProject.Name;
            var projectPath = item.ContainingProject.FullName;
            projectPath = projectPath.Substring(0, projectPath.LastIndexOf('\\'));
            var temp = filename.Replace(projectPath, "").Trim('\\');
            return $"{projectName}.{temp.Replace('\\', '.')}";
        }

        /// <summary>
        ///     显示消息
        /// </summary>
        /// <param name="msg"></param>
        private void ShowMessage(string msg)
        {
            VsShellUtilities.ShowMessageBox(
                package,
                msg,
                "Command",
                OLEMSGICON.OLEMSGICON_INFO,
                OLEMSGBUTTON.OLEMSGBUTTON_OK,
                OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
        }
    }
}
